#include <stdio.h>
#include <stdlib.h>
#include "lexer.h"      // 移除 compiler/ 前缀
#include "token.h"      // 移除 compiler/ 前缀

// 测试词法分析器的函数
void test_lexer(const char* input) {
    printf("\n测试输入: %s\n", input);
    printf("Token序列:\n");
    printf("%-15s %-15s %-10s %-10s\n", "类型", "词素", "行号", "列号");
    printf("-----------------------------------------------------------\n");
    
    // 创建词法分析器
    Lexer* lexer = create_lexer(input);
    
    // 获取所有Token并打印
    Token* token;
    TokenType type;  // 在循环前声明type变量
    do {
        token = get_next_token(lexer);
        if (!token) {
            printf("错误: 无法获取Token\n");
            break;
        }
        type = token->type;  // 保存Token类型
        printf("%-15s %-15s %-10d %-10d\n", 
               token_type_to_string(type), 
               token->lexeme, 
               token->line, 
               token->column);
        free_token(token);  // 释放Token
    } while (type != EOF_TOKEN && type != ERROR);  // 使用保存的类型进行循环判断
    
    // 释放词法分析器
    free_lexer(lexer);
    printf("\n测试完成\n\n");
}

// 运行多个测试用例
int main() {
    system("chcp 65001");
    
    printf("=== SQL词法分析器测试 ===\n\n");
    
    // 测试1: 关键字和标识符
    test_lexer("SELECT id, name FROM users");
    
    // 测试2: 带有WHERE子句的SELECT语句
    test_lexer("SELECT * FROM products WHERE price > 100.0");
    
    // 测试3: CREATE TABLE语句
    test_lexer("CREATE TABLE customers (id INT, name VARCHAR, age INT)");
    
    // 测试4: INSERT语句
    test_lexer("INSERT INTO orders VALUES (1, 'Product A', 19.99)");
    
    // 测试5: 运算符和表达式
    test_lexer("x + y * (z - 10) / 5");
    
    // 测试6: 比较运算符
    test_lexer("a = b AND c <> d OR e <= f AND g >= h");
    
    // 测试7: 注释处理
    test_lexer("SELECT * FROM table -- This is a comment\nWHERE id = 5");
    
    // 测试8: 字符串和数字
    test_lexer("'Hello World' 123 45.67");
    
    // 测试9: 错误处理 - 未闭合的字符串
    test_lexer("SELECT 'unclosed string");
    
    // 测试10: 错误处理 - 无效字符
    test_lexer("SELECT @invalid_char");
    
    printf("=== 所有测试用例执行完毕 ===\n");
    
    system("pause");
    
    return 0;
}